package plugins;

import org.mybatis.generator.api.GeneratedJavaFile;
import org.mybatis.generator.api.IntrospectedTable;
import org.mybatis.generator.api.PluginAdapter;
import org.mybatis.generator.api.dom.java.*;

import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;

import static org.mybatis.generator.internal.util.StringUtility.stringHasValue;
import static org.mybatis.generator.internal.util.messages.Messages.getString;

public class ControllerAndServicePlugin extends PluginAdapter {
    //实体类名
    private String entityName;
    private String interfaceTargetProject ;
    private String interfaceTargetPackage;
    private  String controllerTargetProject;
    private  String controllerTargetPackage;
    private String mapperPath;

    public boolean validate(List<String> warnings) {
        boolean valid = true;
         interfaceTargetProject = properties
                .getProperty("interfaceTargetProject");
         interfaceTargetPackage = properties
                .getProperty("interfaceTargetPackage");
         controllerTargetProject = properties
                .getProperty("controllerTargetProject");
        controllerTargetPackage = properties
                .getProperty("controllerTargetPackage");
        if (!stringHasValue(interfaceTargetProject)) { //$NON-NLS-1$
            warnings.add(getString("ValidationError.18", //$NON-NLS-1$
                    "MapperConfigPlugin", //$NON-NLS-1$
                    "interfaceTargetProject")); //$NON-NLS-1$
            valid = false;
        }
        if (!stringHasValue(interfaceTargetPackage)) { //$NON-NLS-1$
            warnings.add(getString("ValidationError.18", //$NON-NLS-1$
                    "MapperConfigPlugin", //$NON-NLS-1$
                    "interfaceTargetPackage")); //$NON-NLS-1$
            valid = false;
        }

        if (!stringHasValue(controllerTargetProject)) { //$NON-NLS-1$
            warnings.add(getString("ValidationError.18", //$NON-NLS-1$
                    "MapperConfigPlugin", //$NON-NLS-1$
                    "controllerTargetProject")); //$NON-NLS-1$
            valid = false;
        }
        if (!stringHasValue(controllerTargetPackage)) { //$NON-NLS-1$
            warnings.add(getString("ValidationError.18", //$NON-NLS-1$
                    "MapperConfigPlugin", //$NON-NLS-1$
                    "controllerTargetPackage")); //$NON-NLS-1$
            valid = false;
        }
        return valid;
    }

    /**
     * 获取需要的信息
     * @param interfaze
     * @param topLevelClass
     * @param introspectedTable
     * @return
     */
    @Override
    public boolean clientGenerated(Interface interfaze, TopLevelClass topLevelClass, IntrospectedTable introspectedTable) {
        mapperPath = interfaze.getType().getFullyQualifiedName();
        FullyQualifiedJavaType fullyQualifiedJavaType = new FullyQualifiedJavaType(introspectedTable.getBaseRecordType());
        entityName = fullyQualifiedJavaType.getShortName();

        return true;
    }

    @Override
    public List<GeneratedJavaFile> contextGenerateAdditionalJavaFiles(IntrospectedTable introspectedTable) {
        List<GeneratedJavaFile> answer = new ArrayList<GeneratedJavaFile>(1);
        String isServiceNeed = introspectedTable.getTableConfigurationProperty("service");
        if ("false".equals(isServiceNeed)){
            System.out.println("service配置为false，跳过生成service");
        }else {
            genServiceInterface(answer, introspectedTable);
            genServiceImpl(answer, introspectedTable);
        }
        genController(answer, introspectedTable);
        return answer;
    }

    private void genController(List<GeneratedJavaFile> answer, IntrospectedTable introspectedTable) {
        //先判断，如果文件已经存在则不再生成
        //如果配置了不生成controller = false 则直接返回
        String isControllerNeed = introspectedTable.getTableConfigurationProperty("controller");
        if ("false".equals(isControllerNeed)){
            System.out.println("controller配置为false，跳过生成controller");
            return;
        }
        String filePathTemp = controllerTargetProject+"/"+controllerTargetPackage+"."+entityName + "Controller";
        String filePath = filePathTemp.replaceAll("\\.", "/")+".java";
        File file = new File(filePath);
        if (file.exists()){
            System.out.println("文件已经存在，不再重复生成："+filePath);
            return;
        }
        System.out.println("第一次生成文件："+filePath);
        Set<FullyQualifiedJavaType> importTypes = new TreeSet<FullyQualifiedJavaType>();

        TopLevelClass serviceClass = new TopLevelClass(controllerTargetPackage+"."+entityName + "Controller");

        serviceClass.setVisibility(JavaVisibility.PUBLIC);
        //加注解
        serviceClass.addAnnotation("@RestController");
        importTypes.add(new FullyQualifiedJavaType("org.springframework.web.bind.annotation.RestController;"));
        importTypes.add(new FullyQualifiedJavaType("org.springframework.beans.factory.annotation.Autowired;"));
        //加属性
        FullyQualifiedJavaType serviceType = new FullyQualifiedJavaType(interfaceTargetPackage + "." + entityName + "Service");
        Field field = new Field(getFieldName()+"Service",serviceType);
        importTypes.add(serviceType);
        field.setVisibility(JavaVisibility.PRIVATE);
        field.addAnnotation("@Autowired");
        serviceClass.addField(field);
        serviceClass.addImportedTypes(importTypes);
        GeneratedJavaFile gjf = new GeneratedJavaFile(serviceClass, controllerTargetProject, context.getJavaFormatter());
        answer.add(gjf);
    }

    private void genServiceImpl(List<GeneratedJavaFile> answer, IntrospectedTable introspectedTable) {
        //先判断，如果文件已经存在则不再生成
        String filePathTemp = interfaceTargetProject+"/"+interfaceTargetPackage+"/impl/"+entityName + "ServiceImpl";
        String filePath = filePathTemp.replaceAll("\\.", "/")+".java";
        File file = new File(filePath);
        if (file.exists()){
            System.out.println("文件已经存在，不再重复生成："+filePath);
            return;
        }
        System.out.println("第一次生成文件："+filePath);
        Set<FullyQualifiedJavaType> importTypes = new TreeSet<FullyQualifiedJavaType>();

        TopLevelClass serviceClass = new TopLevelClass(interfaceTargetPackage+".impl."+entityName + "ServiceImpl");

        serviceClass.setVisibility(JavaVisibility.PUBLIC);
        FullyQualifiedJavaType serviceType = new FullyQualifiedJavaType(interfaceTargetPackage+"."+entityName+"Service");
        serviceClass.addSuperInterface(serviceType);
        importTypes.add(serviceType);
        //加注解
        serviceClass.addAnnotation("@Service");
        importTypes.add(new FullyQualifiedJavaType("org.springframework.stereotype.Service;"));
        importTypes.add(new FullyQualifiedJavaType("org.springframework.beans.factory.annotation.Autowired;"));
        //加属性
        FullyQualifiedJavaType mapperType = new FullyQualifiedJavaType(mapperPath);
        Field field = new Field(getFieldName()+"Mapper",mapperType);
        importTypes.add(mapperType);
        field.setVisibility(JavaVisibility.PRIVATE);
        field.addAnnotation("@Autowired");
        serviceClass.addField(field);
        serviceClass.addImportedTypes(importTypes);
        //新增baseServiceImp
        FullyQualifiedJavaType baseServiceImplJavaType = new FullyQualifiedJavaType("BaseServiceImpl");
        FullyQualifiedJavaType entityType = new FullyQualifiedJavaType(introspectedTable.getBaseRecordType());
        baseServiceImplJavaType.addTypeArgument(entityType);
        FullyQualifiedJavaType baseServiceImplJavaTypeImport = new FullyQualifiedJavaType("www.app.com.common.base.BaseServiceImpl");
        serviceClass.addImportedType(baseServiceImplJavaTypeImport);
        //实现继承
        serviceClass.setSuperClass(baseServiceImplJavaType);
        serviceClass.addImportedType(entityType);
        //新增俩个方法public Object getMapper()  public Object newExample()
        Method getMapper = new Method();
        getMapper.setVisibility(JavaVisibility.PUBLIC);
        getMapper.setName("getMapper");
        getMapper.addBodyLine("return " + getFieldName()+"Mapper" + ";");
        getMapper.addAnnotation("@Override");
        getMapper.setReturnType(FullyQualifiedJavaType.getObjectInstance());
        Method newExample = new Method();
        newExample.setVisibility(JavaVisibility.PUBLIC);
        newExample.setName("newExample");
        String exampleName = entityType.getFullyQualifiedName() + "Example";
        FullyQualifiedJavaType exampleType = new FullyQualifiedJavaType(exampleName);
        newExample.addBodyLine("return " + "new "+exampleType.getShortName()+ "();");
        newExample.addAnnotation("@Override");
        newExample.setReturnType(FullyQualifiedJavaType.getObjectInstance());
        serviceClass.addMethod(getMapper);
        serviceClass.addMethod(newExample);
        serviceClass.addImportedType(exampleType);
        GeneratedJavaFile gjf = new GeneratedJavaFile(serviceClass, interfaceTargetProject, context.getJavaFormatter());
        answer.add(gjf);
    }

    private void genServiceInterface(List<GeneratedJavaFile> answer, IntrospectedTable introspectedTable) {
        //先判断，如果文件已经存在则不再生成
        String filePathTemp = interfaceTargetProject+"/"+interfaceTargetPackage +"."+entityName+ "Service";
        String filePath = filePathTemp.replaceAll("\\.", "/")+".java";
        File file = new File(filePath);
        if (file.exists()){
            System.out.println("文件已经存在，不再重复生成："+filePath);
            return;
        }
        System.out.println("第一次生成文件："+filePath);
        Set<FullyQualifiedJavaType> importTypes = new TreeSet<FullyQualifiedJavaType>();

        Interface mapperExtInterface = new Interface(interfaceTargetPackage+"." +entityName + "Service");
        mapperExtInterface.setVisibility(JavaVisibility.PUBLIC);
        //新增BaseService
        FullyQualifiedJavaType baseServiceJaveImportType = new FullyQualifiedJavaType("www.app.com.common.base.BaseService");
        FullyQualifiedJavaType baseServiceJavaType = new FullyQualifiedJavaType("BaseService");
        importTypes.add(baseServiceJaveImportType);
        FullyQualifiedJavaType entityType = new FullyQualifiedJavaType(introspectedTable.getBaseRecordType());
        importTypes.add(entityType);
        baseServiceJavaType.addTypeArgument(entityType);
        Interface baseService = new Interface(baseServiceJavaType);
        mapperExtInterface.addSuperInterface(baseServiceJavaType);
        mapperExtInterface.addImportedTypes(importTypes);
        GeneratedJavaFile gjf = new GeneratedJavaFile(mapperExtInterface, interfaceTargetProject, context.getJavaFormatter());
        answer.add(gjf);
    }

    private String getFieldName(){
        return   (entityName.charAt(0)+"").toLowerCase()+entityName.substring(1);
    }

}
